package com.ironman.mes.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.solon.dao.SaTokenDaoOfRedis;
import cn.dev33.satoken.solon.integration.SaTokenInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.ironman.mes.entity.Res;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

@Slf4j
@Configuration
public class AuthConfig {

    private static final String[] EXCLUDE_PATHS = {"/favicon.ico", "/_run/stop", "/healthz", "/solon-admin/**"};

    private static final String[] CUSTOM_EXCLUDE_PATHS = {"/auth/login", "/plugin/**", "/demo/**"};

    @Bean
    public SaTokenDao saTokenDao(@Inject("${sa-token-dao}") SaTokenDaoOfRedis saTokenDao) {
        return saTokenDao;
    }

    @Bean(index = -100)  //-100，是顺序位（低值优先）
    public SaTokenInterceptor saTokenInterceptor() {
        return new SaTokenInterceptor()
                // 指定 [拦截路由] 与 [放行路由]
                .addInclude("/**")
                .addExclude(EXCLUDE_PATHS)
                .addExclude(CUSTOM_EXCLUDE_PATHS)
                // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(req -> {
                    String requestPath = SaHolder.getRequest().getRequestPath();
                    String method = SaHolder.getRequest().getMethod();
                    log.info("在每次[认证函数]之前执行 requestPath {} method {}", requestPath, method);
                })
                // 认证函数: 每次请求执行
                .setAuth(req -> {
                    SaRouter.match("/**", StpUtil::checkLogin);
                })
                // 异常处理函数：每次认证函数发生异常时执行此函数 //包括注解异常
                .setError(this::handError);
    }

    private Res<String> handError(Throwable e) {
        SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
        if (e instanceof NotLoginException) {
            NotLoginException notLoginException = (NotLoginException) e;
            String type = notLoginException.getType();
            return Res.failure(type, e.getMessage());
        }
        return Res.failure("unknown", e.getMessage());
    }
}